// DlgBuffs.cpp: Implementierungsdatei
//

#include "stdafx.h"
#include "Charplan.h"
#include "DlgBuffs.h"
#include "CharplanDoc.h"
#include "math.h"


// CDlgBuffs-Dialogfeld

CDlgBuffs::struct_buff& CDlgBuffs::struct_buff::operator=(const CDlgBuffs::struct_buff& rhs)
{
    type = rhs.type;
    buffer_class_number = rhs.buffer_class_number;
    spell_name = rhs.spell_name;
    level = rhs.level;
    value = rhs.value;
    required_level = rhs.required_level;
    required_skill = rhs.required_skill;

    return *this;
}

CDlgBuffs::struct_buffer& CDlgBuffs::struct_buffer::operator=(const CDlgBuffs::struct_buffer& rhs)
{
    name = rhs.name;
    skill_line = rhs.skill_line;
    level = rhs.level;
    skill = rhs.skill;
    buff_bonus = rhs.buff_bonus;

    return *this;
}




IMPLEMENT_DYNAMIC(CDlgBuffs, CDialog)

CDlgBuffs::CDlgBuffs(CCharplanDoc* pc_doc, CWnd* pParent /*=NULL*/)
        : CDialog(CDlgBuffs::IDD, pParent)
{
    mpc_doc = pc_doc;
    LevelChanged();
}


CDlgBuffs::~CDlgBuffs()
{
}

void CDlgBuffs::LevelChanged()
{
    mn_level = (int)mpc_doc->GetLevel();
}

void CDlgBuffs::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT1, mwnd_buff_char_class[0]);
    DDX_Control(pDX, IDC_EDIT2, mwnd_buff_char_class[1]);
    DDX_Control(pDX, IDC_EDIT3, mwnd_buff_char_class[2]);
    DDX_Control(pDX, IDC_EDIT16, mwnd_buff_char_class[3]);
    DDX_Control(pDX, IDC_EDIT20, mwnd_buff_char_class[4]);
    DDX_Control(pDX, IDC_EDIT34, mwnd_buff_char_class[5]);
    DDX_Control(pDX, IDC_EDIT35, mwnd_buff_char_class[6]);
    DDX_Control(pDX, IDC_EDIT47, mwnd_buff_char_class[7]);
    DDX_Control(pDX, IDC_EDIT52, mwnd_buff_char_class[8]);
    DDX_Control(pDX, IDC_EDIT24, mwnd_buff_char_level[0]);
    DDX_Control(pDX, IDC_EDIT25, mwnd_buff_char_level[1]);
    DDX_Control(pDX, IDC_EDIT30, mwnd_buff_char_level[2]);
    DDX_Control(pDX, IDC_EDIT37, mwnd_buff_char_level[3]);
    DDX_Control(pDX, IDC_EDIT38, mwnd_buff_char_level[4]);
    DDX_Control(pDX, IDC_EDIT45, mwnd_buff_char_level[5]);
DDX_Control(pDX, IDC_EDIT41, mwnd_buff_char_level[6]);
DDX_Control(pDX, IDC_EDIT50, mwnd_buff_char_level[7]);
DDX_Control(pDX, IDC_EDIT55, mwnd_buff_char_level[8]);
    DDX_Control(pDX, IDC_EDIT4, mwnd_buff_char_skillline[0]);
    DDX_Control(pDX, IDC_EDIT5, mwnd_buff_char_skillline[1]);
    DDX_Control(pDX, IDC_EDIT6, mwnd_buff_char_skillline[2]);
    DDX_Control(pDX, IDC_EDIT17, mwnd_buff_char_skillline[3]);
    DDX_Control(pDX, IDC_EDIT31, mwnd_buff_char_skillline[4]);
    DDX_Control(pDX, IDC_EDIT43, mwnd_buff_char_skillline[5]);
    DDX_Control(pDX, IDC_EDIT39, mwnd_buff_char_skillline[6]);
    DDX_Control(pDX, IDC_EDIT48, mwnd_buff_char_skillline[7]);
    DDX_Control(pDX, IDC_EDIT53, mwnd_buff_char_skillline[8]);
    DDX_Control(pDX, IDC_EDIT7, mwnd_buff_char_skill[0]);
    DDX_Control(pDX, IDC_EDIT8, mwnd_buff_char_skill[1]);
    DDX_Control(pDX, IDC_EDIT10, mwnd_buff_char_skill[2]);
    DDX_Control(pDX, IDC_EDIT18, mwnd_buff_char_skill[3]);
    DDX_Control(pDX, IDC_EDIT32, mwnd_buff_char_skill[4]);
    DDX_Control(pDX, IDC_EDIT44, mwnd_buff_char_skill[5]);
DDX_Control(pDX, IDC_EDIT40, mwnd_buff_char_skill[6]);
DDX_Control(pDX, IDC_EDIT49, mwnd_buff_char_skill[7]);
DDX_Control(pDX, IDC_EDIT54, mwnd_buff_char_skill[8]);
    DDX_Control(pDX, IDC_EDIT9, mwnd_buff_char_buffbonus[0]);
    DDX_Control(pDX, IDC_EDIT11, mwnd_buff_char_buffbonus[1]);
    DDX_Control(pDX, IDC_EDIT12, mwnd_buff_char_buffbonus[2]);
    DDX_Control(pDX, IDC_EDIT19, mwnd_buff_char_buffbonus[3]);
    DDX_Control(pDX, IDC_EDIT33, mwnd_buff_char_buffbonus[4]);
    DDX_Control(pDX, IDC_EDIT46, mwnd_buff_char_buffbonus[5]);
DDX_Control(pDX, IDC_EDIT42, mwnd_buff_char_buffbonus[6]);
DDX_Control(pDX, IDC_EDIT51, mwnd_buff_char_buffbonus[7]);
DDX_Control(pDX, IDC_EDIT56, mwnd_buff_char_buffbonus[8]);
    DDX_Control(pDX, IDC_EDIT13, mwnd_buff_value[0]);
    DDX_Control(pDX, IDC_EDIT14, mwnd_buff_value[1]);
    DDX_Control(pDX, IDC_EDIT15, mwnd_buff_value[2]);
    DDX_Control(pDX, IDC_EDIT21, mwnd_buff_value[3]);
    DDX_Control(pDX, IDC_EDIT22, mwnd_buff_value[4]);
    DDX_Control(pDX, IDC_EDIT23, mwnd_buff_value[5]);
    DDX_Control(pDX, IDC_COMBO5, mwnd_buff[0]);
    DDX_Control(pDX, IDC_COMBO6, mwnd_buff[1]);
    DDX_Control(pDX, IDC_COMBO7, mwnd_buff[2]);
    DDX_Control(pDX, IDC_COMBO13, mwnd_buff[3]);
    DDX_Control(pDX, IDC_COMBO14, mwnd_buff[4]);
    DDX_Control(pDX, IDC_COMBO15, mwnd_buff[5]);
    DDX_Control(pDX, IDC_BUFF_GROUP, mwnd_group);
}




BEGIN_MESSAGE_MAP(CDlgBuffs, CDialog)
    ON_CBN_SELCHANGE(IDC_COMBO5, &CDlgBuffs::OnCbnSelchangeCombo5)
    ON_CBN_SELCHANGE(IDC_COMBO6, &CDlgBuffs::OnCbnSelchangeCombo6)
    ON_CBN_SELCHANGE(IDC_COMBO7, &CDlgBuffs::OnCbnSelchangeCombo7)
    ON_CBN_SELCHANGE(IDC_COMBO13, &CDlgBuffs::OnCbnSelchangeCombo13)
    ON_CBN_SELCHANGE(IDC_COMBO14, &CDlgBuffs::OnCbnSelchangeCombo14)
    ON_CBN_SELCHANGE(IDC_COMBO15, &CDlgBuffs::OnCbnSelchangeCombo15)
    ON_EN_CHANGE(IDC_EDIT24, &CDlgBuffs::OnEnChangeEdit24)
    ON_EN_CHANGE(IDC_EDIT25, &CDlgBuffs::OnEnChangeEdit25)
    ON_EN_CHANGE(IDC_EDIT30, &CDlgBuffs::OnEnChangeEdit30)
    ON_EN_CHANGE(IDC_EDIT37, &CDlgBuffs::OnEnChangeEdit37)
    ON_EN_CHANGE(IDC_EDIT38, &CDlgBuffs::OnEnChangeEdit38)
    ON_EN_CHANGE(IDC_EDIT45, &CDlgBuffs::OnEnChangeEdit45)
    ON_EN_CHANGE(IDC_EDIT41, &CDlgBuffs::OnEnChangeEdit41)
    ON_EN_CHANGE(IDC_EDIT50, &CDlgBuffs::OnEnChangeEdit50)
    ON_EN_CHANGE(IDC_EDIT55, &CDlgBuffs::OnEnChangeEdit55)
    ON_EN_CHANGE(IDC_EDIT7, &CDlgBuffs::OnEnChangeEdit7)
    ON_EN_CHANGE(IDC_EDIT8, &CDlgBuffs::OnEnChangeEdit8)
    ON_EN_CHANGE(IDC_EDIT10, &CDlgBuffs::OnEnChangeEdit10)
    ON_EN_CHANGE(IDC_EDIT18, &CDlgBuffs::OnEnChangeEdit18)
    ON_EN_CHANGE(IDC_EDIT32, &CDlgBuffs::OnEnChangeEdit32)
    ON_EN_CHANGE(IDC_EDIT44, &CDlgBuffs::OnEnChangeEdit44)
    ON_EN_CHANGE(IDC_EDIT40, &CDlgBuffs::OnEnChangeEdit40)
    ON_EN_CHANGE(IDC_EDIT49, &CDlgBuffs::OnEnChangeEdit49)
    ON_EN_CHANGE(IDC_EDIT54, &CDlgBuffs::OnEnChangeEdit54)
    ON_EN_CHANGE(IDC_EDIT9, &CDlgBuffs::OnEnChangeEdit9)
    ON_EN_CHANGE(IDC_EDIT11, &CDlgBuffs::OnEnChangeEdit11)
    ON_EN_CHANGE(IDC_EDIT12, &CDlgBuffs::OnEnChangeEdit12)
    ON_EN_CHANGE(IDC_EDIT19, &CDlgBuffs::OnEnChangeEdit19)
    ON_EN_CHANGE(IDC_EDIT33, &CDlgBuffs::OnEnChangeEdit33)
    ON_EN_CHANGE(IDC_EDIT46, &CDlgBuffs::OnEnChangeEdit46)
    ON_EN_CHANGE(IDC_EDIT42, &CDlgBuffs::OnEnChangeEdit42)
    ON_EN_CHANGE(IDC_EDIT51, &CDlgBuffs::OnEnChangeEdit51)
    ON_EN_CHANGE(IDC_EDIT56, &CDlgBuffs::OnEnChangeEdit56)
    ON_EN_KILLFOCUS(IDC_EDIT9, &CDlgBuffs::OnEnKillfocusEdit9)
    ON_EN_KILLFOCUS(IDC_EDIT11, &CDlgBuffs::OnEnKillfocusEdit11)
    ON_EN_KILLFOCUS(IDC_EDIT12, &CDlgBuffs::OnEnKillfocusEdit12)
    ON_EN_KILLFOCUS(IDC_EDIT19, &CDlgBuffs::OnEnKillfocusEdit19)
    ON_EN_KILLFOCUS(IDC_EDIT33, &CDlgBuffs::OnEnKillfocusEdit33)
    ON_EN_KILLFOCUS(IDC_EDIT46, &CDlgBuffs::OnEnKillfocusEdit46)
    ON_EN_KILLFOCUS(IDC_EDIT42, &CDlgBuffs::OnEnKillfocusEdit42)
    ON_EN_KILLFOCUS(IDC_EDIT51, &CDlgBuffs::OnEnKillfocusEdit51)
    ON_EN_KILLFOCUS(IDC_EDIT56, &CDlgBuffs::OnEnKillfocusEdit56)
    ON_WM_DRAWITEM()
END_MESSAGE_MAP()




BOOL CDlgBuffs::PreTranslateMessage(MSG* pMsg)
{
    mToolTips.RelayEvent(pMsg);
    return CDialog::PreTranslateMessage(pMsg);
}


// CDlgBuffs-Meldungshandler

BOOL CDlgBuffs::OnInitDialog()
{

    // special case: vampire: NO buffs
    if (gdbinterface.GetClassID() == ECI_Vampiir)
    {
        AfxMessageBox(IDS_VAMPIIR_HAS_NO_BUFFS);
        EndDialog(IDCANCEL);
        return FALSE;
    }



    CDialog::OnInitDialog();

    // M.Jurkait [6/26/2006]
    // -------------------------
    // Tooltips
    // -------------------------
    mToolTips.Create(this);
    mToolTips.SetDelayTime(TTDT_AUTOPOP,0);
    mToolTips.SetDirection(PPTOOLTIP_TOPEDGE_LEFT);
    mToolTips.SetBehaviour(PPTOOLTIP_CLOSE_LEAVEWND);
    mToolTips.SetDelayTime(TTDT_INITIAL,500);



    GetAllBuffs();


    // M.Jurkait [6/25/2006]
    // -------------------------
    // Get Buff-Classes
    // -------------------------
    ASSERT(ma_buffers.GetCount()<=max_buffers);
    for (INT_PTR t=0;t<ma_buffers.GetCount();t++)
    {
        bool self = ma_buffers[t].name.IsEmpty();
        if (self)
        {
            mwnd_buff_char_class[t].SetWindowText(_T("-SELF-"));
            CString temp;
            temp.Format(_T("%i"),mn_level);
            mwnd_buff_char_level[t].SetWindowText(temp);

            temp.Format(_T("%i"),mpc_doc->GetSpecLevel(ma_buffers[t].skill_line)+(int)(mpc_doc->GetRR()/10));
            mwnd_buff_char_skill[t].SetWindowText(temp);

            mwnd_buff_char_buffbonus[t].SetWindowText(_T("25 %"));
        }
        else
        {
            mwnd_buff_char_class[t].SetWindowText(ma_buffers[t].name);
            mwnd_buff_char_level[t].SetWindowText(_T("50"));
            mwnd_buff_char_skill[t].SetWindowText(_T("50"));
            mwnd_buff_char_buffbonus[t].SetWindowText(_T("25 %"));
        }

        mwnd_buff_char_skillline[t].SetWindowText(ma_buffers[t].skill_line);


        mwnd_buff_char_class[t].EnableWindow();
        mwnd_buff_char_skillline[t].EnableWindow();
        mwnd_buff_char_level[t].EnableWindow(!self);
        mwnd_buff_char_skill[t].EnableWindow(!self);
        mwnd_buff_char_buffbonus[t].EnableWindow();

        mwnd_buff_char_class[t].ShowWindow(SW_SHOW);
        mwnd_buff_char_skillline[t].ShowWindow(SW_SHOW);
        mwnd_buff_char_level[t].ShowWindow(SW_SHOW);
        mwnd_buff_char_skill[t].ShowWindow(SW_SHOW);
        mwnd_buff_char_buffbonus[t].ShowWindow(SW_SHOW);
    }
    for (INT_PTR t=ma_buffers.GetCount();t<max_buffers;t++)
    {
        mwnd_buff_char_class[t].SetWindowText(_T("-------"));
        mwnd_buff_char_skillline[t].SetWindowText(_T("-------"));

        mwnd_buff_char_level[t].SetWindowText(_T("--"));
        mwnd_buff_char_skill[t].SetWindowText(_T("--"));
        mwnd_buff_char_buffbonus[t].SetWindowText(_T("--"));

        mwnd_buff_char_class[t].EnableWindow(FALSE);
        mwnd_buff_char_skillline[t].EnableWindow(FALSE);
        mwnd_buff_char_level[t].EnableWindow(FALSE);
        mwnd_buff_char_skill[t].EnableWindow(FALSE);
        mwnd_buff_char_buffbonus[t].EnableWindow(FALSE);

        mwnd_buff_char_class[t].ShowWindow(SW_HIDE);
        mwnd_buff_char_skillline[t].ShowWindow(SW_HIDE);
        mwnd_buff_char_level[t].ShowWindow(SW_HIDE);
        mwnd_buff_char_skill[t].ShowWindow(SW_HIDE);
        mwnd_buff_char_buffbonus[t].ShowWindow(SW_HIDE);
    };


    ReorderView();


    // M.Jurkait [6/25/2006]
    // -------------------------
    // Fill buffers
    // -------------------------
    UpdateBuffers();

    return TRUE;
}



//////////////////////////////////////////////////////////////////////////
INT_PTR  CDlgBuffs::AddBuffer(const CString& name, const CString& skill)
{
    INT_PTR buff_idx = 0;
    for (;buff_idx<ma_buffers.GetCount();buff_idx++)
        if (ma_buffers[buff_idx].name==name &&
                ma_buffers[buff_idx].skill_line==skill)
        {
            ASSERT(ma_buffers[buff_idx].skill_line==skill);
            return buff_idx;
        }

    struct_buffer newbuff;
    newbuff.name = name;
    newbuff.skill_line = skill;
    newbuff.level = 50;
    newbuff.skill = 50;
    newbuff.buff_bonus = 25;

    return ma_buffers.Add(newbuff);
}



//////////////////////////////////////////////////////////////////////////
bool CDlgBuffs::AddBuffSpell(int type, const CString& bname, bool base, bool self)
{
    // M.Jurkait [6/13/2006]
    // -------------------------
    // Get spells
    // -------------------------
    if (base) gdbinterface.SelectSpellCatBase(bname);
    else  gdbinterface.SelectSpellCatSpec(bname);

    CStringArray names;
    IntArray levels;
    IntArray ids;

    gdbinterface.GetListOfSpells(&names,&levels,&ids);

    // M.Jurkait [6/13/2006]
    // -------------------------
    // check if this is self buff
    // -------------------------
    gdbinterface.SelectSpellID(ids[0]);
    bool is_self=false;
    CStringArray key,val;
    gdbinterface.GetSpellDescription(key,val);
    ASSERT(key[2]=="Target");
    if (val[2]=="Self" || val[2]=="Selbst") is_self = true;
#ifdef _DEBUG
    else
    {
        ASSERT(
            val[2]=="Enemy" || val[2]=="Group"  || val[2]=="Friend" || val[2]=="Realm" ||
            val[2]=="Feind" || val[2]=="Gruppe" || val[2]=="Freund" || val[2]=="Reich"
        );
    }
#endif


    if (is_self && !self) return false;


    // buff_class_index
    for (int t=0;t<names.GetCount();t++)
    {
        gdbinterface.SelectSpellID(ids[t]);
        CString eff = gdbinterface.GetSpellDescriptionEffect();

        ASSERT(eff[0]=='+');
        while (!isdigit(eff[0]))
        {
            ASSERT(!eff.IsEmpty());
            eff.Delete(0);
        }

        struct_buff newbuff;
        newbuff.type = type;
        newbuff.spell_name = names[t];
        newbuff.level = levels[t];
        newbuff.value = _tstoi(eff);

        newbuff.required_level = 0;
        newbuff.required_skill = 0;
        if (base)
            newbuff.required_level = levels[t];
        else
            newbuff.required_skill = levels[t];


        if (!is_self)
        {
            newbuff.buffer_class_number = AddBuffer(gdbinterface.GetClassName().c_str(),gdbinterface.GetSpellLineNameBase());;
            ma_all_buffs.Add(newbuff);
        }

        // self buff
        if (self)
        {
            newbuff.buffer_class_number=AddBuffer(CString(""),gdbinterface.GetSpellLineNameBase());
            ma_all_buffs.Add(newbuff);
        }
    }

    return false;
}



void CDlgBuffs::GetAllBuffs()
{
    ma_all_buffs.RemoveAll();
    ma_buffers.RemoveAll();


    // backup
    int current_class = gdbinterface.GetClassID();
    int current_race = gdbinterface.GetRaceID();

    int old_realm = gdbinterface.GetRealm();

    if (mpc_doc->GetOption(_T("CoopMode")))
    {
        gdbinterface.SelectRealm(-1);
    }
    

    IntArray class_ids;
    gdbinterface.GetListOfClasses(class_ids);


    for (int cl=0;cl<class_ids.GetCount();cl++)
    {
        gdbinterface.SelectClass(class_ids[cl]);

        bool self_allowed = (class_ids[cl]==current_class);

        CStringArray spell_lines;
        gdbinterface.GetListOfSpellLines(spell_lines);

        for (int spl=0;spl<spell_lines.GetCount();spl++)
        {
            gdbinterface.SelectSpellLine(spell_lines[spl]);

            CStringArray spell_cats;
            IntArray  spell_types;

            // Base
            gdbinterface.GetListOfSpellCatsBaseAndID(spell_cats, spell_types);

            for (int spc=0;spc<spell_cats.GetCount();spc++)
            {
                if (spell_types[spc] == STI_BUFF_STR)  AddBuffSpell(0,spell_cats[spc], true, self_allowed);
                else
                    if (spell_types[spc] == STI_BUFF_CON)  AddBuffSpell(1,spell_cats[spc], true, self_allowed);
                    else
                        if (spell_types[spc] == STI_BUFF_DEX)  AddBuffSpell(2,spell_cats[spc], true, self_allowed);
            }

            // Spec
            gdbinterface.GetListOfSpellCatsSpecAndID(spell_cats, spell_types);

            for (int spc=0;spc<spell_cats.GetCount();spc++)
            {
                if (spell_types[spc] == STI_BUFF_STR_CON) AddBuffSpell(3,spell_cats[spc], false, self_allowed);
                else
                    if (spell_types[spc] == STI_BUFF_DEX_QUI) AddBuffSpell(4,spell_cats[spc], false, self_allowed);
                    else
                        if (spell_types[spc] == STI_BUFF_ACUITY)  AddBuffSpell(5,spell_cats[spc], false, self_allowed);
                        else
                            if (spell_types[spc] == STI_BUFF_STR)     AddBuffSpell(0,spell_cats[spc], false, self_allowed);
                            else
                                if (spell_types[spc] == STI_BUFF_CON)     AddBuffSpell(1,spell_cats[spc], false, self_allowed);
            }
        }
    }


    // M.Jurkait [6/26/2006]
    // -------------------------
    // sort buffers
    // -------------------------
    CArray<int> maps;
    for (int t=0;t<ma_buffers.GetCount();t++) maps.Add(t);

    for (int t1=0;t1<ma_buffers.GetCount()-1;t1++)
        for (int t2=t1+1;t2<ma_buffers.GetCount();t2++)
        {
            if (ma_buffers[t1].name>ma_buffers[t2].name || ma_buffers[t2].name.IsEmpty())
            {
                struct_buffer temp = ma_buffers[t1];
                ma_buffers[t1] = ma_buffers[t2];
                ma_buffers[t2] = temp;
                int t = maps[t1];
                maps[t1] = maps[t2];
                maps[t2] = t;
            }
        }
    // invert
    CArray<int> imaps;
    imaps.SetSize(maps.GetSize());
    for (int t=0;t<maps.GetCount();t++) imaps[maps[t]]=t;

    for (int t=0;t<ma_all_buffs.GetCount();t++)
    {
        ma_all_buffs[t].buffer_class_number = imaps[ma_all_buffs[t].buffer_class_number];
    }


    gdbinterface.SelectRealm(old_realm);
    gdbinterface.SelectClass(current_class);
    gdbinterface.SelectRace(current_race);
}






void CDlgBuffs::OnEnChangeEdit24()  { LevelChange(0,false);}
void CDlgBuffs::OnEnChangeEdit25()  { LevelChange(1,false);}
void CDlgBuffs::OnEnChangeEdit30()  { LevelChange(2,false);}
void CDlgBuffs::OnEnChangeEdit37()  { LevelChange(3,false);}
void CDlgBuffs::OnEnChangeEdit38()  { LevelChange(4,false);}
void CDlgBuffs::OnEnChangeEdit45()  { LevelChange(5,false);}
void CDlgBuffs::OnEnChangeEdit41()  { LevelChange(6,false);}
void CDlgBuffs::OnEnChangeEdit50()  { LevelChange(7,false);}
void CDlgBuffs::OnEnChangeEdit55()  { LevelChange(8,false);}
void CDlgBuffs::OnEnChangeEdit7()   { LevelChange(0,true);}
void CDlgBuffs::OnEnChangeEdit8()   { LevelChange(1,true);}
void CDlgBuffs::OnEnChangeEdit10()  { LevelChange(2,true);}
void CDlgBuffs::OnEnChangeEdit18()  { LevelChange(3,true);}
void CDlgBuffs::OnEnChangeEdit32()  { LevelChange(4,true);}
void CDlgBuffs::OnEnChangeEdit44()  { LevelChange(5,true);}
void CDlgBuffs::OnEnChangeEdit40()  { LevelChange(6,true);}
void CDlgBuffs::OnEnChangeEdit49()  { LevelChange(7,true);}
void CDlgBuffs::OnEnChangeEdit54()  { LevelChange(8,true);}
void CDlgBuffs::OnEnChangeEdit9()   { BuffBonusChanged(0); }
void CDlgBuffs::OnEnChangeEdit11()  { BuffBonusChanged(1); }
void CDlgBuffs::OnEnChangeEdit12()  { BuffBonusChanged(2); }
void CDlgBuffs::OnEnChangeEdit19()  { BuffBonusChanged(3); }
void CDlgBuffs::OnEnChangeEdit33()  { BuffBonusChanged(4); }
void CDlgBuffs::OnEnChangeEdit46()  { BuffBonusChanged(5); }
void CDlgBuffs::OnEnChangeEdit42()  { BuffBonusChanged(6); }
void CDlgBuffs::OnEnChangeEdit51()  { BuffBonusChanged(7); }
void CDlgBuffs::OnEnChangeEdit56()  { BuffBonusChanged(8); }
void CDlgBuffs::OnEnKillfocusEdit9()  { BuffBonusFormat(0);}
void CDlgBuffs::OnEnKillfocusEdit11() { BuffBonusFormat(1);}
void CDlgBuffs::OnEnKillfocusEdit12() { BuffBonusFormat(2);}
void CDlgBuffs::OnEnKillfocusEdit19() { BuffBonusFormat(3);}
void CDlgBuffs::OnEnKillfocusEdit33() { BuffBonusFormat(4);}
void CDlgBuffs::OnEnKillfocusEdit46() { BuffBonusFormat(5);}
void CDlgBuffs::OnEnKillfocusEdit42() { BuffBonusFormat(6);}
void CDlgBuffs::OnEnKillfocusEdit51() { BuffBonusFormat(7);}
void CDlgBuffs::OnEnKillfocusEdit56() { BuffBonusFormat(8);}


void CDlgBuffs::BuffBonusChanged(int type)
{
    if (type>=ma_buffers.GetCount()) return;

    CString temp;
    mwnd_buff_char_buffbonus[type].GetWindowText(temp);
    ma_buffers[type].buff_bonus = min(25,max(0,_tstoi(temp)));

    OnCbnSelchangeCombo5();
    OnCbnSelchangeCombo6();
    OnCbnSelchangeCombo7();
    OnCbnSelchangeCombo13();
    OnCbnSelchangeCombo14();
    OnCbnSelchangeCombo15();
}


void CDlgBuffs::BuffBonusFormat(int type)
{
    if (type>=ma_buffers.GetCount()) return;

    CString temp;
    temp.Format(_T("%i %%"),ma_buffers[type].buff_bonus);
    mwnd_buff_char_buffbonus[type].SetWindowText(temp);
}



void CDlgBuffs::LevelChange(int type, bool skill)
{
    if (type>=ma_buffers.GetCount()) return;

    CString temp;

    if (skill)
    {
        mwnd_buff_char_skill[type].GetWindowText(temp);
        // 50 + rr13 + 11 items (<- dont know if items are counted)
        ma_buffers[type].skill = min(73,max(1,_tstoi(temp)));
    }
    else
    {
        mwnd_buff_char_level[type].GetWindowText(temp);
        // 50 + rr13 + 11 items (<- dont know if items are counted)
        ma_buffers[type].level = min(73,max(1,_tstoi(temp)));
    }


    OnCbnSelchangeCombo5();
    OnCbnSelchangeCombo6();
    OnCbnSelchangeCombo7();
    OnCbnSelchangeCombo13();
    OnCbnSelchangeCombo14();
    OnCbnSelchangeCombo15();
}



CString CDlgBuffs::GetBuffBase(int nr)
{
    ASSERT(nr>=0 && nr<=3);

    if (mn_buff_value[nr]==0) return CString(_T(""));

    CString temp;
    temp.Format(_T("%i"),mn_buff_value[nr]);
    return temp;
}


CString CDlgBuffs::GetBuffSpec(int nr)
{
    ASSERT(nr>=0 && nr<=3);

    if (mn_buff_value[nr+3]==0) return CString(_T(""));

    CString temp;
    temp.Format(_T("%i"),mn_buff_value[nr+3]);
    return temp;
}



void CDlgBuffs::OnCbnSelchangeCombo5()
{
    UpdateBuff(BUFF_STR,mn_level+mn_level/4);
}

void CDlgBuffs::OnCbnSelchangeCombo6()
{
    UpdateBuff(BUFF_CON,mn_level+mn_level/4);
}

void CDlgBuffs::OnCbnSelchangeCombo7()
{
    UpdateBuff(BUFF_DEX,mn_level+mn_level/4);
}

void CDlgBuffs::OnCbnSelchangeCombo13()
{
    UpdateBuff(BUFF_STRCON,(int)(1875*mn_level/1000));
}

void CDlgBuffs::OnCbnSelchangeCombo14()
{
    UpdateBuff(BUFF_DEXQUI,(int)(1875*mn_level/1000));
}

void CDlgBuffs::OnCbnSelchangeCombo15()
{
    UpdateBuff(BUFF_INT,(int)(162*mn_level/100));
}



void CDlgBuffs::UpdateBuff(int type, int cap)
{
    int buffer_idx = mwnd_buff[type].GetCurSel();
    if (buffer_idx == CB_ERR) return;
    buffer_idx = (int)mwnd_buff[type].GetItemData(buffer_idx);

    // no buff
    if (buffer_idx==-1)
    {
        mn_buff_value[type] = 0;
        mwnd_buff_value[type].SetWindowText(_T(""));
        CString temp = _T("no buff-char selected");
        mToolTips.UpdateTipText(temp,&mwnd_buff_value[type]);
        mToolTips.UpdateTipText(temp,&mwnd_buff[type]);
        return;
    }

    // direct buff
    if (buffer_idx<0)
    {
        mn_buff_value[type] = -buffer_idx;

        CString temp;
        temp.Format(_T("+%i"),mn_buff_value[type]);
        mwnd_buff_value[type].SetWindowText(temp);

        temp = _T("Elixir/Champ-buff");
        mToolTips.UpdateTipText(temp,&mwnd_buff_value[type]);
        mToolTips.UpdateTipText(temp,&mwnd_buff[type]);
        return;
    }

    // find highest buff
    int spell = -1;
    for (int t=0;t<ma_all_buffs.GetCount();t++)
    {
        if (ma_all_buffs[t].type != type || ma_all_buffs[t].buffer_class_number != buffer_idx) continue;

        if (ma_all_buffs[t].required_level > ma_buffers[buffer_idx].level ||
                ma_all_buffs[t].required_skill > ma_buffers[buffer_idx].skill) continue;

        if (spell<0 || ma_all_buffs[t].level > ma_all_buffs[spell].level)
            spell = t;
    }

    if (spell<0)
    {
        mn_buff_value[type] = 0;
        mwnd_buff_value[type].SetWindowText(_T(""));

        CString temp = _T("no buff spell at this level/skill");
        mToolTips.UpdateTipText(temp,&mwnd_buff_value[type]);
        mToolTips.UpdateTipText(temp,&mwnd_buff[type]);

        return;
    }


    // M.Jurkait [6/26/2006]
    // -------------------------
    // Calculation
    // -------------------------
    int skillfak = 75 + min(50,50*ma_buffers[buffer_idx].skill/(ma_all_buffs[spell].level+1));
    int rv = ma_all_buffs[spell].value * skillfak / 100;
    int rv_bb = rv*(100+ma_buffers[buffer_idx].buff_bonus)/100;

    mn_buff_value[type] = min(rv_bb,cap);


    CString temp;
    temp.Format(_T("+%i"),mn_buff_value[type]);
    mwnd_buff_value[type].SetWindowText(temp);
// mwnd_buff_name[type].SetWindowText(ma_all_buffs[spell].spell_name);

    CString temp2;
    if (mn_buff_value[type] < rv_bb)
    {
        temp2.Format(_T("(capped to %i points)"),mn_buff_value[type]);
    }

    int bbreq = max(0,(int)(ceil((float)cap*100.0f/rv)))-100;


    temp.Format(_T("%s<br>")
                _T("lvl%i %s<br><br>")
                _T("%i Buff-value<br>")
                _T("*%i %% Skill-factor (=%i)<br>")
                _T("+%i %% Buff-Bonus (+%i)<br><hr><br>")
                _T("%i points %s<br><br>")
                _T("(%i %% buff-bonus required for cap)"),
                ma_buffers[buffer_idx].name,
                ma_all_buffs[spell].level, ma_all_buffs[spell].spell_name,
                ma_all_buffs[spell].value,
                skillfak,rv,
                ma_buffers[buffer_idx].buff_bonus,rv_bb-rv,
                rv_bb,temp2,
                max(0,bbreq)
               );

    mToolTips.UpdateTipText(temp,&mwnd_buff_value[type]);
    mToolTips.UpdateTipText(temp,&mwnd_buff[type]);
}



//////////////////////////////////////////////////////////////////////////
void CDlgBuffs::UpdateBuffers()
{
    INT_PTR last_buffer = -2;
    int last_type = -2;

    // Add NONE Buffers
    for (int t=0;t<6;t++)
    {
        mwnd_buff[t].ResetContent();
        int idx = mwnd_buff[t].AddString(_T("---------"),-1);
        mwnd_buff[t].SetCurSel(idx);
    }

    // Add Buffers
    for (int t=0;t<ma_all_buffs.GetCount();t++)
    {
        if (last_type == ma_all_buffs[t].type && last_buffer == ma_all_buffs[t].buffer_class_number) continue;

        last_type = ma_all_buffs[t].type;
        last_buffer = ma_all_buffs[t].buffer_class_number;

        int t1= 0;
        for (;t1<mwnd_buff[last_type].GetCount();t1++)
            if (mwnd_buff[last_type].GetItemData(t1) == last_buffer) break;

        if (t1>=mwnd_buff[last_type].GetCount())
        {
            CString name = ma_buffers[last_buffer].name;
            if (name.IsEmpty()) name = "-SELF-";
            int idx = mwnd_buff[last_type].AddString(name,last_buffer);
        }
    }

    // Add Champ/Potions/RvR
    mwnd_buff[BUFF_STR].AddString(_T("Elixier"),-34,RGB(96,96,96));
    mwnd_buff[BUFF_CON].AddString(_T("Elixier"),-34,RGB(96,96,96));
    mwnd_buff[BUFF_DEX].AddString(_T("Elixier"),-34,RGB(96,96,96));
    mwnd_buff[BUFF_STRCON].AddString(_T("Elixier"),-51,RGB(96,96,96));
    mwnd_buff[BUFF_DEXQUI].AddString(_T("Elixier"),-51,RGB(96,96,96));
    mwnd_buff[BUFF_INT].AddString(_T("Elixier"),-34,RGB(96,96,96));

    mwnd_buff[BUFF_STR].AddString(_T("Champ-Buff (CL1)"),-26,RGB(64,96,96));
    mwnd_buff[BUFF_CON].AddString(_T("Champ-Buff (CL2)"),-26,RGB(64,96,96));
    mwnd_buff[BUFF_DEX].AddString(_T("Champ-Buff (CL2)"),-26,RGB(64,96,96));
    mwnd_buff[BUFF_STRCON].AddString(_T("Champ-Buff (CL3)"),-30,RGB(64,96,96));
    mwnd_buff[BUFF_DEXQUI].AddString(_T("Champ-Buff (CL4)"),-30,RGB(64,96,96));
    mwnd_buff[BUFF_INT].AddString(_T("Champ-Buff (CL5)"),-20,RGB(64,96,96));

    mwnd_buff[BUFF_STR].AddString(_T("Buff NPC"),-50,RGB(64,96,96));
    mwnd_buff[BUFF_CON].AddString(_T("Buff NPC"),-50,RGB(64,96,96));
    mwnd_buff[BUFF_DEX].AddString(_T("Buff NPC"),-50,RGB(64,96,96)); // ? "boB ONES" said: qui = 50
    mwnd_buff[BUFF_STRCON].AddString(_T("Buff NPC"),-80,RGB(64,96,96));
    mwnd_buff[BUFF_DEXQUI].AddString(_T("Buff NPC"),-80,RGB(64,96,96));
    mwnd_buff[BUFF_INT].AddString(_T("Buff NPC"),-56,RGB(64,96,96));


    // pre select
    int self_id = (ma_buffers.GetSize()>0 && ma_buffers[0].name.IsEmpty())?0:-99;
    int main_buffer = -99;
    const CString mainbuffers("Druid Druide Kleriker Cleric Schamane Shaman");
    for (int t=0;t<ma_buffers.GetCount();t++)
        if (!ma_buffers[t].name.IsEmpty() && mainbuffers.Find(ma_buffers[t].name)!=-1)
        {
            main_buffer = t;
            break;
        }

    for (int t=0;t<6;t++)
    {
        int sel = -1;
        for (int t1=0;t1<mwnd_buff[t].GetCount();t1++)
        {
            if (mwnd_buff[t].GetItemData(t1) == self_id)
            {
                sel = t1;
                break;
            }

            if (mwnd_buff[t].GetItemData(t1) == main_buffer)
            {
                sel = t1;
            }
        }

        if (sel>-1)
        {
            mwnd_buff[t].SetCurSel(sel);
        }
    }

    // force buff-update
    OnCbnSelchangeCombo5();
    OnCbnSelchangeCombo6();
    OnCbnSelchangeCombo7();
    OnCbnSelchangeCombo13();
    OnCbnSelchangeCombo14();
    OnCbnSelchangeCombo15();
}




void CDlgBuffs::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    // TODO: Add your message handler code here and/or call default

    CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}



BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
     CArray<HWND> *childs = (CArray<HWND>*)lParam;
     childs->Add(hwnd);
     return TRUE;
}

void CDlgBuffs::ReorderView()
{
    // find all windows below buffer grp
    CArray<HWND> childs;
    EnumChildWindows(m_hWnd,EnumChildProc,(LPARAM)&childs);

    CRect grp;
    mwnd_group.GetWindowRect(grp);
    ScreenToClient(grp);

    struct struct_win
    {
        HWND   hwnd;
        CPoint pos;
    };

    CArray<struct_win> lower_win;
    for (int i=0;i<childs.GetCount();++i)
    {
        RECT r;
        ::GetWindowRect(childs[i],&r);
        ScreenToClient(&r);
        if (r.top > grp.bottom)
        {
            struct_win w;
            w.hwnd = childs[i];
            w.pos = CPoint(r.left,r.top);
            lower_win.Add(w);
        }
    }

    // get last visible pos
    CRect last;
    mwnd_buff_char_class[ma_buffers.GetCount()-1].GetWindowRect(last);
    ScreenToClient(&last);

    // move windows
    int dy = last.bottom - grp.bottom+5;
    for (int t=0;t<lower_win.GetCount();++t)
    {
        ::SetWindowPos(lower_win[t].hwnd,NULL,lower_win[t].pos.x,lower_win[t].pos.y+dy,0,0,SWP_NOZORDER|SWP_NOSIZE);
    }
    mwnd_group.SetWindowPos(NULL,0,0,grp.Width(),grp.Height()+dy,SWP_NOZORDER|SWP_NOMOVE);

    GetWindowRect(grp);
    SetWindowPos(NULL,0,0,grp.Width(),grp.Height()+dy,SWP_NOZORDER|SWP_NOMOVE);
}

